<template>
  <div class="map-container">
    <div id="map"></div>
    <Spin fix v-show="inLoading" style="background: transparent;">
      <div style="position: absolute; width: 100%;height: 100%; background: white; opacity: 0.6; top: 0;"></div>
      <div style="border: 1px solid #ddd; border-radius: 4px; width: 86px; height: 80px; background: white; margin-left: 50%; transform: translateX(-50%);">
        <Icon type="load-c" size=24 class="spin-icon-load" style="margin-top: 20px"></Icon>
        <div>加载中</div>
      </div>
    </Spin>
    <Select v-model="currentBuilding" style="width:200px; right: 20px;top: 10px; position: absolute" @on-change="changeBuilding" v-show="allowChangeBuilding">
      <Option v-for="item in buildingList" :value="item.value" :key="item.value">{{ item.label }}</Option>
    </Select>
    <Select v-model="selectedCategory" style="width:200px; right: 20px;top: 50px; position: absolute" @on-change="changeShowCategory" filterable v-show="allowFilterDevice">
      <Option v-for="item in typeList" :value="item.value" :key="item.value" :label="item.label">
        <span>{{ item.label }}</span><img style="float:right; width: 18px;" :src="`${$mapServer}/icons/${item.value}.png`" v-if="item.value!='all'">
      </Option>
    </Select>
    <slot name="filter"></slot>
    <div class="animation-player-container" v-show="trolleyAnimationPlay">
      <Button type="primary" shape="circle" icon="play" size="small" v-show="trolleyAnimationPaused" @click="resumeTrolleyAnimation"></Button>
      <Button type="primary" shape="circle" icon="pause" size="small" v-show="!trolleyAnimationPaused" @click="pauseTrolleyAnimation"></Button>
      <Button type="primary" shape="circle" icon="stop" size="small" @click="exitTrolleyAnimation"></Button>
      <Progress :percent="trolleyAnimationPercent*100" :stroke-width="5" style="width: 240px;" status="active">
        <span>{{trolleyAnimationTime}}</span>
      </Progress>
    </div>
  </div>
</template>

<script type="es6">

import Indoor from '../../assets/Indoor.js';
import mapStyle from '../../assets/mapStyle.json'
window.NGR = Indoor;

export default {
  props: {
    auto: { default: true },
    roomClickable: { default: false },
    roomHoverSilence: { default: false },
    allowChangeBuilding: { default: true },
    allowFilterDevice: { default: true },
    allowFilterPatient: { default: false },
    customHoverConf: { default: undefined },
    animatedTrack: { default: true },
  },
  name: 'Map',
  mounted() {
    //      if (this.$route.params.lat && this.$route.params.lng && this.$route.params.floorid) {
    //        this.initMap(this.$route.params.lat, this.$route.params.lng, this.$route.params.floorid);
    //      }
    //      else {
    if (this.auto) this.initMap();
    if (this.allowFilterDevice) this.initSelection();
    this.$emit('changeBuilding', this.currentBuilding);
    //      }
  },
  data() {
    return {
      floorData: {},
      buildingData: {},
      map: {},
      roomInfo: true,
      deviceInfo: false,
      markerInfo: false,
      clickedTarget: '',
      originalFacility: [],
      lastPos: {},
      currentFloor: '',
      inLoading: true,
      inIcon: false,
      extraData: undefined,
      icon: Indoor.icon({
        iconUrl: `https://yxys.io/icons/marker.png`,
        iconSize: [20, 20],
      }),
      trashIcon: Indoor.icon({
        iconUrl: `https://yxys.io/icons/trash-icon.png`,
        iconSize: [20, 20],
      }),
      cabinetIcon: Indoor.icon({
        iconUrl: `https://yxys.io/icons/cabinet.png`,
        iconSize: [20, 20],
      }),
      mapStyle: mapStyle,
      popup: {},
      res: {},
      layers: {},
      control: Indoor.control.floor(),
      currentBuilding: '0',
      buildingList: [
        {
          value: '0',
          label: '建筑一'
        },
        {
          value: '1',
          label: '建筑二'
        }
      ],
      patientsData: {
        features: [
          {
            geometry: {
              coordinates: [432710.8534474953, 108824.90209870049],
              type: "Point",
            },
            properties: {
              father: '102',
              id: 'test1',
              location_type: 'LOCATION',
              logo: 'slight',
              name: '测试1',
              planar_graph: "YD00002701101",
              update_time: "2017-05-01 23:29:13",
            },
            type: "Feature"
          }]
      },
      selectedCategory: 'hospital',
      typeList: [],
      polyLinePoints: [],
      trolleyAnimationInterval: {},
      trolleyAnimationPath: [],
      // 推车动画的线，注意多层情况
      trolleyAnimationPolylines: [],
      // 推车动画播放模式
      trolleyAnimationPlay: false,
      // 推车动画暂停
      trolleyAnimationPaused: false,
      trolleyAnimationIndex: 0,
      trolleyFrameCounter: 0,
      trolleyFrameIntervalX: 0,
      trolleyFrameIntervalY: 0,
      trolleyAnimationPercent: 0,
      trolleyAnimationTime: '加载中',
      pathModeInfo: {}
    }
  },
  watch: {
    currentFloor(floorId) {
      if (floorId != '') {
        this.$emit('changeFloor', {
          floorId: floorId,
          floorName: this.floorData.data.floor_name,
          playingAnimation: this.trolleyAnimationPlay
        });
      }
    },
    currentBuilding(buildingId) {
      this.$emit('changeBuilding', buildingId);
    }
  },
  methods: {
    startLoading() {
      this.inLoading = true;
    },
    stopLoading() {
      this.inLoading = false;
    },
    initMap() {
      this.control.on('change', async (e) => {
        if (this.currentFloor === e.to) return
        await this.loadFloor(e.to);
        this.currentFloor = e.to;
        if (this.roomClickable) this.initClick();
        // 如果之前不是显示房间信息
        if (this.selectedCategory !== 'hospital') this.changeShowCategory(this.selectedCategory);
      });
      this.map = new Indoor.View('map', {
        appKey: "c7bc846ea1a14e7dad270c979888e4a3"
      })
      this.res = new Indoor.DataSource({
        appKey: "c7bc846ea1a14e7dad270c979888e4a3"
      });
      this.map.addControl(this.control);
      this.loadBuilding(0);
    },
    // 显示路径
    loadPolyLine(polylinePath) {
      let tmpPath = polylinePath.map((item) => {
        let tmpPoint = Indoor.CRS.EPSG3857.unproject(Indoor.point([item[0], item[1]]))
        return [tmpPoint.lat, tmpPoint.lng]
      });
      this.layers.polylineLayer = Indoor.polyline(tmpPath, { color: 'forestgreen', weight: 2 });
      if (this.map.hasLayer(this.layers.polylineLayer)) this.map.removeLayer(this.layers.polylineLayer);
      this.map.addLayer(this.layers.polylineLayer);
    },

    // 显示电子围栏
    loadLimitPolygon(polygonPath) {
      let tmpPath = polygonPath.map((item) => {
        let tmpPoint = Indoor.CRS.EPSG3857.unproject(Indoor.point([item[0], item[1]]))
        return [tmpPoint.lat, tmpPoint.lng]
      });
      this.layers.polygonLayer = Indoor.polygon(tmpPath, { color: 'blue', weight: 1 });
      if (this.map.hasLayer(this.layers.polygonLayer)) this.map.removeLayer(this.layers.polygonLayer);
      this.map.addLayer(this.layers.polygonLayer);
    },
    removeLimitPolygon() {
      if (this.map.hasLayer(this.layers.polygonLayer)) this.map.removeLayer(this.layers.polygonLayer);
    },
    removePolyLine() {
      if (this.map.hasLayer(this.layers.polylineLayer)) {
        this.map.removeLayer(this.layers.polylineLayer);
      }
    },
    // 重设电子围栏
    editingPath() {
      if (this.map.hasLayer(this.layers.polygonLayer)) this.map.removeLayer(this.layers.polygonLayer);
      this.polyLinePoints = [];
      this.map.on('click', (e) => {
        this.polyLinePoints.push([e.latlng.lat, e.latlng.lng]);
        this.$emit('pathPointAdded', this.polyLinePoints);
        if (this.polyLinePoints.length > 1) {
          if (this.map.hasLayer(this.layers.polylineLayer)) this.map.removeLayer(this.layers.polylineLayer);
          this.layers.polylineLayer = Indoor.polyline(this.polyLinePoints, { color: 'forestgreen', weight: 3 });
          this.map.addLayer(this.layers.polylineLayer);
        }
      });
      this.map.on('contextmenu', (e) => {
        this.polyLinePoints.pop();
        this.$emit('pathPointAdded', this.polyLinePoints);
        if (this.polyLinePoints.length > 0) {
          if (this.map.hasLayer(this.layers.polylineLayer)) this.map.removeLayer(this.layers.polylineLayer);
          this.layers.polylineLayer = Indoor.polyline(this.polyLinePoints, { color: 'forestgreen', weight: 3 });
          this.map.addLayer(this.layers.polylineLayer);
        }
      })
    },
    // 停止编辑电子围栏 finished为确认，否则为取消
    stopEditingPath(finished) {
      this.polyLinePoints = [];
      this.map.off('click');
      this.map.off('contextmenu');
      this.polyLinePoints = [];
      if (!finished && this.map.hasLayer(this.layers.polylineLayer)) {
        this.map.removeLayer(this.layers.polylineLayer);
      }
    },
    async initSelection() {
      let tmpType = await this.$getRemoteData(`${this.$mapServer}/services/config/child/0/0/0`, { method: 'get' });
      this.typeList = [{
        value: 'hospital',
        label: '房间信息'
      }].concat(tmpType.data.categories.map((item) => {
        return { label: item.category_name, value: item.icon }
      }));
    },
    removeControl() {
      this.map.removeControl(this.control);
    },
    loadControl() {
      this.map.addControl(this.control);
    },
    // 画特定设备
    loadMarker(lat, lng, markerInfo, iconUrl, iconSize = [20,20]) {
      let randomIndex = Math.round(Math.random() * 10);
      let IconDict = ['ap', 'inject', 'toilet', 'radio', 'meeting', 'medicine', 'atm', 'check', 'prepare', 'flower', 'microscope'];
      const iconName = iconUrl || IconDict[randomIndex];
      let randomIcon = Indoor.icon({
        iconUrl: `https://yxys.io/icons/${iconName}.png`,
        iconSize
      })
      this.tmpIconURL = `https://yxys.io/icons/${iconName}.png`
      let marker = Indoor.marker(Indoor.latLng(lat, lng), { icon: randomIcon, markerInfo });
      this.layers.markerLayer.clearLayers();
      this.layers.markerLayer.addLayer(marker);
      this.bindEvents();
    },
    // 画定位marker
    loadLocationMarker(lat, lng, logo, iconSize = [20,20]) {
      let marker = Indoor.marker(Indoor.CRS.EPSG3857.unproject(Indoor.point([lat, lng])), {
        icon: Indoor.icon({
          iconUrl: `https://yxys.io/icons/${logo ? logo : 'marker'}.png`,
          iconSize
        })
      });
      this.layers.markerLayer.clearLayers();
      this.layers.markerLayer.addLayer(marker);
      this.bindEvents();
    },
    // 为地图增加额外marker，用于筛选和展示, data是需并入的marker的数组
    setExtraData(data) {
      let layerInfo = this.formatFloorData(this.floorData.data.mapInfo);
      layerInfo.Facility.features = layerInfo.Facility.features.concat(data);
      this.originalFacility = layerInfo.Facility;
      this.extraData = data;
    },
    // 读取楼层信息
    async loadFloor(floorId, lat, lng) {
      return new Promise(async (resolve, rej) => {
        this.inLoading = true;
        try {
          this.$Loading.start();
          this.floorData = await this.$getRemoteData(`${this.$mapServer}/services/map/floor/${floorId}`, { method: 'get' });
          let layerInfo = this.formatFloorData(this.floorData.data.mapInfo);
          if (this.extraData !== undefined) layerInfo.Facility.features = layerInfo.Facility.features.concat(this.extraData);
          this.originalFacility = layerInfo.Facility;
          // 保存原有初始设备
          this.map.clear();
          this.control.setCurrentFloor(floorId);
          this.layers.frame = Indoor.featureLayer(layerInfo.Frame, {
            layerType: 'Frame',
            styleConfig: this.mapStyle
          });
          this.layers.area = Indoor.featureLayer(layerInfo.Area, {
            layerType: 'Area',
            styleConfig: this.mapStyle
          });
          this.layers.annotation = Indoor.featureLayer(layerInfo.Area, {
            layerType: 'LogoLabel',
            styleConfig: this.mapStyle
          });
          this.layers.facility = Indoor.featureLayer(layerInfo.Facility, {
            layerType: 'Facility',
            styleConfig: this.mapStyle
          });
          this.layers.collision = Indoor.layerGroup.collision({ margin: 3 });
          if (this.roomInfo) this.layers.collision.addLayer(this.layers.annotation);
          if (this.deviceInfo) this.layers.collision.addLayer(this.layers.facility);
          this.layers.markerLayer = Indoor.layerGroup();

          // 将图层添加到地图中
          this.map.addLayer(this.layers.frame);
          this.map.addLayer(this.layers.area);
          this.map.addLayer(this.layers.collision);
          this.map.addLayer(this.layers.markerLayer);
          this.map.render();
          this.bindEvents('hospital');
          this.$Loading.finish();
          this.inLoading = false;
          this.$emit('changeFloor', {
            floorId: floorId,
            floorName: this.floorData.data.floor_name,
            playingAnimation: this.trolleyAnimationPlay
          });
          resolve('loaded');
        }
        catch (e) {
          rej(e)
        }
      });
    },
    // 读取建筑物信息
    async loadBuilding(n) {
      this.buildingData = await this.$getRemoteData(`${this.$mapServer}/services/map/building/${n}`, { method: 'get' })
      let floors = this.buildingData.data.floors.map((item, index) => {
        return {
          address: item['floor_name'],
          default: index === 0,
          id: item['floor_id'],
          parent: this.buildingData.data.parentId,
          type: "FLOOR"
        }
      });
      this.control.setFloorList(floors);
      await this.loadFloor(floors[0].id);
      this.currentFloor = floors[0].id;
      if (this.selectedCategory !== 'hospital') this.changeShowCategory(this.selectedCategory);
      this.$emit('initiated');
      if (this.roomClickable) this.initClick();
    },
    bindEvents() {
      if (this.roomInfo && !this.roomHoverSilence) {
        this.layers.area.eachLayer((layer) => {
          layer.on('mouseover', (e) => {
            if (this.lastPos.lat) {
              if (this.lastPos.lat === e.latlng.lat && this.lastPos.lng === e.latlng.lng) {
                return
              }
              if (e.target.options.fillColor != '#e8ccb3') {
                e.target.setStyle({ fillColor: '#e8ccb3' });
              }
              if ((Math.pow((e.latlng.lat - this.lastPos.lat), 2) + Math.pow((e.latlng.lng - this.lastPos.lng), 2)) < 1) {
                return
              }
            }
            let logoLabel = e.target.feature.properties['logo'] != 'null' ? `<img src="https://yxys.io/icons/${e.target.feature.properties['logo']}.png" style="height: 20px; position: absolute; right: 20px; top: 16px;">` : '';
            this.popup = NGR.popup({ closeButton: false })
              .setLatLng(e.latlng)
              .setContent(`<div class="room-info info-pop"><p>房间信息</p>${logoLabel}
<div>房间名：<span class="room-name">${e.target.feature.properties['name']}</span></div>
<div>房间编号：${e.target.feature.properties['FT_ID']}</div>
<div>更新时间：${e.target.feature.properties['update_time']}</div></div>`)
              .openOn(this.map);
            this.lastPos = e.latlng;
          });

          layer.on('mouseout', (e) => {
            if (e.target != this.clickedTarget) {
              e.target.setStyle({ fillColor: this.mapStyle.Area.filter[0].values[e.target.feature.properties.category].fillColor });
              this.popup._close();
              this.lastPos = '';
            }
          })
        });
        this.layers.facility.eachLayer((layer) => {
          layer.off('mouseover');
          layer.off('mouseout');
        })
      }
      else if (this.deviceInfo) {
        this.layers.facility.eachLayer((layer) => {
          layer.on('mouseover', (e) => {
            if (this.inIcon) {
              return
            }
            let tmpText;
            if (this.customHoverConf) {
              tmpText = `<div class="device-info info-pop"><p style="color: #5cadff; font-weight: bold">${this.customHoverConf.title}</p>`
              let item;
              for (item of this.customHoverConf.content) {
                tmpText = tmpText + `<div>${item.label}：<span style="color: ${item.color}; bold: ${item.bold ? 'bold' : 'normal'}">${e.target.feature.properties[item.feature]}</span></div>`
              }
            }
            else {
              let tmpReminder = ['slight', 'medium', 'danger'].includes(e.target.feature.properties.logo) ? '患者' : '设备';
              tmpText = `<div class="device-info info-pop"><p style="color: #5cadff; font-weight: bold">${tmpReminder + '信息'}</p>
<div>${tmpReminder + '名称'}：<span class="room-name">${e.target.feature.properties['name']}</span></div>
<div>${tmpReminder + '编号'}：${e.target.feature.properties['id']}</div>
<div>${tmpReminder + '类型'}：${e.target.feature.properties['category']}</div>
<div>${tmpReminder + '更新时间'}：${e.target.feature.properties['update_time']}</div></div>`
            }
            this.popup = NGR.popup({ closeButton: false })
              .setLatLng(e.latlng)
              .setContent(tmpText)
              .openOn(this.map);
            this.inIcon = true;
          });
          layer.on('mouseout', (e) => {
            this.inIcon = false
            this.popup._close();
          });
        });
        this.layers.area.eachLayer((layer) => {
          layer.off('mouseover');
          layer.off('mouseout');
        })
      }
      else if (this.markerInfo) {
        this.layers.markerLayer.eachLayer((layer) => {
          layer.on('mouseover', (e) => {
            let tmpText;
            if (this.customHoverConf) {
              tmpText = `<div class="device-info info-pop"><p style="color: #5cadff; font-weight: bold">${this.customHoverConf.title}</p>`
              let item;
              for (item of this.customHoverConf.content) {
                if (item.link) {
                  tmpText = tmpText + `<div><span style="text-decoration: underline; cursor: pointer;" class="indoor-show-path">${item.label}</span></div>`
                }
                else {
                  tmpText = tmpText + `<div>${item.label}：<span style="color: ${item.color}; bold: ${item.bold ? 'bold' : 'normal'};">${e.target.options.markerInfo[item.feature]}</span></div>`
                }
              }
            }
            else {
              tmpText = e.target.options.markerInfo.type === 'trolley' ?
                `<div class="device-info info-pop"><p style="color: #5cadff; font-weight: bold">推车信息</p>
<div>推车编号：<span class="room-name">${e.target.options.markerInfo.id}</span></div>
<div>推车使用者：${e.target.options.markerInfo.operator}</div>
<div>更新时间：${e.target.options.markerInfo.update_time}</div>
<div><span style="text-decoration: underline; cursor: pointer;" class="indoor-show-path">查看轨迹</span></div>
</div>
` : `<div class="device-info info-pop"><p style="color: #5cadff; font-weight: bold">设备信息</p>
<div>设备名称：<span class="room-name">${e.target.options.markerInfo['name']}</span></div>
<div>设备编号：${e.target.options.markerInfo['id']}</div>
<div>设备类型：${e.target.options.markerInfo['category']}</div></div>`;
            }
            this.popup = NGR.popup({ closeButton: true })
              .setLatLng(e.latlng)
              .setContent(tmpText)
              .openOn(this.map);
            if (e.target.options.markerInfo.type === 'trolley' || e.target.options.markerInfo.mode === 'track') {
              document.getElementsByClassName('indoor-show-path')[0].onclick = () => {
                if (this.trolleyAnimationPlay) {
                  this.$Notice.warning({ title: '当前已是播放模式，请点击右下角按钮控制' })
                  return
                }
                this.pathModeInfo = e.target.options.markerInfo;
                this.$emit('showPath', e.target.options.markerInfo.path);
              }
            }
          });
        })
        this.layers.area.eachLayer((layer) => {
          layer.off('mouseover');
          layer.off('mouseout');
        })
        this.layers.facility.eachLayer((layer) => {
          layer.off('mouseover');
          layer.off('mouseout');
        })
      }
      else {
        this.layers.facility.eachLayer((layer) => {
          layer.off('mouseover');
          layer.off('mouseout');
        })
        this.layers.area.eachLayer((layer) => {
          layer.off('mouseover');
          layer.off('mouseout');
        })
      }
    },
    changeBuilding(buildingId) {
      //        this.loadBuilding(buildingId);
    },
    moveToPoint(lat, lng) {
      this.map.panTo({ lat, lng });
    },
    //      changePatientType(patientType){
    //        this.map.removeLayer(this.layers.collision);
    //        this.layers.collision.removeLayer(this.layers.facility);
    //        this.roomInfo = false;
    //        this.deviceInfo = true;
    //        this.markerInfo = false;
    //        this.selectedPatientType = patientType;
    //        this.layers.facility = Indoor.featureLayer(this.filterPatientsData(patientType), {
    //          layerType: 'Facility',
    //          styleConfig: this.mapStyle
    //        });
    //        console.log(this.layers.facility);
    //        this.layers.collision.addLayer(this.layers.facility);
    //        this.map.addLayer(this.layers.collision);
    //        this.bindEvents();
    //      },
    changeShowCategory(category) {
      try {
        this.map.removeLayer(this.layers.collision);
        this.layers.collision.removeLayer(this.layers.facility);
        this.layers.collision.removeLayer(this.layers.annotation);
      }
      catch (e) {
        console.log(e)
      }
      this.selectedCategory = category;
      if (category === 'hospital') {
        this.roomInfo = true;
        this.deviceInfo = false;
        this.markerInfo = false;
        this.layers.collision.addLayer(this.layers.annotation);
        this.map.addLayer(this.layers.collision);
      }
      else if (category === 'none') {
        this.roomInfo = false;
        this.deviceInfo = false;
        this.markerInfo = true;
        this.layers.facility.clearLayers();
        this.layers.collision.addLayer(this.layers.facility);
        this.map.addLayer(this.layers.collision);
      }
      else {
        this.roomInfo = false;
        this.deviceInfo = true;
        this.markerInfo = false;
        this.layers.facility = Indoor.featureLayer(this.filterDeviceData(category), {
          layerType: 'Facility',
          styleConfig: this.mapStyle
        });
        this.layers.collision.addLayer(this.layers.facility);
        this.map.addLayer(this.layers.collision);
      }
      //        let selectFacilities = {
      //          features: this.originalFacility.features.filter((item) => {
      //            return type === 'all' ? true : item.properties.logo === type
      //          }),
      //          type: "FeatureCollection",
      //        };

      //        this.layers.facility = Indoor.featureLayer(selectFacilities, {
      //          layerType: 'Facility',
      //          styleConfig: this.mapStyle
      //        })
      this.bindEvents();
    },
    exitTrolleyAnimation() {
      clearInterval(this.trolleyAnimationInterval);
      this.trolleyAnimationPlay = false;
      this.trolleyFrameCounter = 0;
      this.trolleyAnimationIndex = 0;
      this.loadControl();
      this.removePolyLine();
      this.removeLimitPolygon();
      this.$emit('exitTrolleyAnimation');
    },
    pauseTrolleyAnimation() {
      clearInterval(this.trolleyAnimationInterval);
      this.trolleyAnimationPaused = true;
    },
    resumeTrolleyAnimation() {
      this.trolleyAnimationInterval = setInterval(() => this.trolleyUpdateMap(), 100);
      this.trolleyAnimationPaused = false;
      // if (this.trolleyAnimationIndex === 0) this.loadPolyLine(this.trolleyAnimationPolylines[0]);
    },
    async trolleyPathAnimation(path) {
      // 起始推车动画
      this.trolleyAnimationPolylines = [];
      let tmpPolylines = [[path[0]]];
      this.trolleyAnimationPlay = true;
      this.removeControl();
      this.trolleyAnimationPath = path;
      this.popup._close();
      // 如果首个位置不在当前楼层
      if (path[0][3] !== this.currentFloor) {
        await this.loadFloor(path[0][3]);
        this.currentFloor = path[0][3];
      }
      this.loadTrolleys([{ lat: path[0][0], lng: path[0][1], info: this.pathModeInfo }]);
      this.trolleyAnimationInterval = setInterval(() => this.trolleyUpdateMap(), 100);
      // 对跨楼层路径分组
      for (let i = 1, max = path.length; i < max; i++) {
        if (path[i][3] === path[i - 1][3]) {
          tmpPolylines[tmpPolylines.length - 1].push(path[i]);
        }
        else {
          // 跨楼后的第一个点应算在前一个楼层
          tmpPolylines[tmpPolylines.length - 1].push(path[i]);
          tmpPolylines.push([path[i]]);
        }
      }
      // 最后缺一个元素，补上
      tmpPolylines[tmpPolylines.length - 1].push(path[path.length - 1]);
      // 分组后存入trolleyAnimationPolylines
      for (let i = 0, max = tmpPolylines.length; i < max; i++) {
        let item;
        for (let j = 0, max = tmpPolylines[i].length - 1; j < max; j++) {
          // 跨楼后的第一个点应算在前一个楼层
          this.trolleyAnimationPolylines.push(tmpPolylines[i])
        }
      }
      if (!!this.animatedTrack) this.loadPolyLine(this.trolleyAnimationPolylines[0]);
    },
    async trolleyUpdateMap() {
      //每个位置首帧，更新信息
      if (this.trolleyFrameCounter === 0) {
        // 如果需要切换楼层
        if (this.trolleyAnimationPath[this.trolleyAnimationIndex][3] !== this.currentFloor) {
          clearInterval(this.trolleyAnimationInterval);
          await this.loadFloor(this.trolleyAnimationPath[this.trolleyAnimationIndex][3]);
          this.currentFloor = this.trolleyAnimationPath[this.trolleyAnimationIndex][3];
          this.trolleyAnimationInterval = setInterval(() => this.trolleyUpdateMap(), 100);
          if (this.trolleyAnimationPolylines[this.trolleyAnimationIndex].length > 1) this.loadPolyLine(this.trolleyAnimationPolylines[this.trolleyAnimationIndex]);
        }
        if (this.trolleyAnimationIndex < this.trolleyAnimationPath.length - 1) {
          this.trolleyFrameIntervalX = (this.trolleyAnimationPath[this.trolleyAnimationIndex + 1][0] - this.trolleyAnimationPath[this.trolleyAnimationIndex][0]) / 40;
          this.trolleyFrameIntervalY = (this.trolleyAnimationPath[this.trolleyAnimationIndex + 1][1] - this.trolleyAnimationPath[this.trolleyAnimationIndex][1]) / 40;
          this.loadTrolleys([{
            lat: this.trolleyAnimationPath[this.trolleyAnimationIndex][0] + (this.animatedTrack ? this.trolleyFrameIntervalX * this.trolleyFrameCounter : 0),
            lng: this.trolleyAnimationPath[this.trolleyAnimationIndex][1] + (this.animatedTrack ? this.trolleyFrameIntervalY * this.trolleyFrameCounter : 0),
            info: this.pathModeInfo
          }]);
          this.trolleyFrameCounter = this.trolleyFrameCounter + 1;
        }
        else {
          // 最后一个位置，不跳回到起始位置
          this.loadTrolleys([{
            lat: this.trolleyAnimationPath[this.trolleyAnimationIndex][0],
            lng: this.trolleyAnimationPath[this.trolleyAnimationIndex][1],
            info: this.pathModeInfo
          }]);
          this.trolleyAnimationIndex = 0;
          this.$Notice.info({ title: '播放完毕!您可选择重新播放。' });
          clearInterval(this.trolleyAnimationInterval);
          this.trolleyAnimationPaused = true;
          return
        }
      }
      //每个位置尾帧，更新信息
      else if (this.trolleyFrameCounter >= 39) {
        this.loadTrolleys([{
          lat: this.trolleyAnimationPath[this.trolleyAnimationIndex][0] + (this.animatedTrack ? this.trolleyFrameIntervalX * this.trolleyFrameCounter : 0),
          lng: this.trolleyAnimationPath[this.trolleyAnimationIndex][1] + (this.animatedTrack ? this.trolleyFrameIntervalY * this.trolleyFrameCounter : 0),
          info: this.pathModeInfo
        }]);
        this.trolleyAnimationIndex = this.trolleyAnimationIndex + 1;
        this.trolleyFrameCounter = 0;
      }
      //每个位置中间帧
      else {
        this.loadTrolleys([{
          lat: this.trolleyAnimationPath[this.trolleyAnimationIndex][0] + (this.animatedTrack ? this.trolleyFrameIntervalX * this.trolleyFrameCounter:0),
          lng: this.trolleyAnimationPath[this.trolleyAnimationIndex][1] + (this.animatedTrack ? this.trolleyFrameIntervalY * this.trolleyFrameCounter:0),
          info: this.pathModeInfo
        }]);
        this.trolleyFrameCounter = this.trolleyFrameCounter + 1;
      }
      this.trolleyAnimationPercent = (this.trolleyFrameCounter + this.trolleyAnimationIndex * 40) / (40 * (this.trolleyAnimationPath.length - 1));
      this.trolleyAnimationTime = this.trolleyAnimationPath[this.trolleyAnimationIndex][2];
    },
    removeTrolleys() {
      this.layers.markerLayer.clearLayers();
      this.markerInfo = false;
    },
    loadTrolleys(trolleyList) {
      let item;
      this.layers.markerLayer.clearLayers();
      this.markerInfo = true;
      for (item of trolleyList) {
        let marker = Indoor.marker(Indoor.CRS.EPSG3857.unproject(Indoor.point([item.lat, item.lng])), {
          icon: Indoor.icon({
            iconUrl: `https://yxys.io/icons/marker.png`,
            iconSize: [20, 20]
          }),
          markerInfo: item.info
        });
        this.layers.markerLayer.addLayer(marker);
      }
      this.bindEvents();
    },
    formatFloorData(floorData) {
      let tmpFrame = (JSON.parse(floorData.profile[0].coordinates)).map((item) => {
        return {
          type: "Feature",
          properties: {
            FL_ID: floorData.profile[0].id
          },
          geometry: {
            type: "Polygon",
            coordinates: item
          }
        }
      })
      let Frame = { "type": "FeatureCollection", "features": tmpFrame };
      let tmpArea = (floorData.room).map((item, index) => {
        return {
          type: "Feature",
          properties: {
            FT_ID: item.roomId,
            FL_ID: item.parentId,
            name: item.type != 0 ? item.name : '',
            category: item.type,
            logo: item.icon,
            desc: item.desc,
            update_time: item.update_time,
            facilities: item.facilities,
            id: index
          },
          geometry: {
            type: "Polygon",
            coordinates: JSON.parse(item.coordinates)
          }
        }
      });
      let Area = { "type": "FeatureCollection", "features": tmpArea };
      let tmpFacility = (floorData.device).map((item, index) => {
        return {
          type: "Feature",
          properties: {
            location_type: "LOCATION",
            name: item.name,
            logo: item.icon,
            father: item.father_id,
            planar_graph: item.parentId,
            update_time: item.update_time,
            id: item.id
          },
          geometry: {
            type: "Point",
            coordinates: item.coordinates.split(',')
          }
        }
      });
      let Facility = { "type": "FeatureCollection", "features": tmpFacility };
      return {
        Frame,
        Area,
        Facility
      }
    },
    filterDeviceData(category) {
      return {
        features: this.originalFacility.features.filter((item) => {
          return item.properties.logo === category
        }),
        type: "FeatureCollection"
      }
    },
    filterPatientsData(patientType) {
      return {
        features: this.patientsData.features.filter((item) => {
          return item.properties.logo === patientType
        }),
        type: "FeatureCollection"
      }
    },
    initClick() {
      this.layers.area.eachLayer((layer) => {
        layer.on('click', (e) => {
          if (this.clickedTarget !== '') {
            this.clickedTarget.setStyle({ fillColor: this.mapStyle.Area.filter[0].values[this.clickedTarget.feature.properties.category].fillColor });
          }
          this.clickedTarget = e.target;
          e.target.setStyle({ fillColor: '#e8ccb3' });
          this.$emit('clickRoom', e);
        })
      })
    },
    addDragMarker(logoURL, x, y) {
      let icon = Indoor.icon({
        iconUrl: logoURL,
        iconSize: [24, 24]
      });
      let ngrP = new Indoor.Point(x, y);
      let tmpP = this.map.containerPointToLatLng(ngrP);
      let marker = Indoor.marker(tmpP, {
        draggable: true,
        icon: icon,
      });
      this.$emit('located', this.map._core_map.options.crs.project(tmpP));
      marker.on('dragend', (e) => {
        this.$emit('located', this.map._core_map.options.crs.project(e.target._latlng));
      });
      this.layers.markerLayer.addLayer(marker);
    },
    clearMarkers() {
      this.layers.markerLayer.clearLayers();
    },
    unbindAreaHover() {
      this.layers.area.eachLayer((layer) => {
        layer.off('mouseover');
        layer.off('mouseout');
      });
    },
    drawHeatmap(heatmapData) {
      if (this.layers.heatmap) this.map.removeLayer(this.layers.heatmap);
      this.layers.heatmap = Indoor.featureLayer(heatmapData, {
        layerType: 'Heatmap',
        styleConfig: this.mapStyle
      });
      this.map.addLayer(this.layers.heatmap);
      this.map.render();
    },
    clearHeatmap() {
      this.map.removeLayer(this.layers.heatmap);
    },
    refresh() {
      return new Promise(async (resolve, rej) => {
        try {
          await this.loadFloor(this.currentFloor);
          if (this.roomClickable) this.initClick();
          resolve();
        }
        catch (e) {
          console.log(e)
          rej(e);
        }
      })
    }
  }
}
</script>

<style>
.info-pop {
  background: #fff;
  width: 100%;
  border-radius: 4px;
  padding: 8px 19px 13px;
}

.room-info {
  border: 1px solid #d7dde4;
}

.device-info {
  border: 1px solid #d7dde4;
}

.ngr-popup-tip-container {
  opacity: 0;
}

.ngr-popup-content-wrapper {
  background: transparent !important;
  box-shadow: 0 0 0 !important;
  border: 0;
  border-radius: 0 !important;
  /*transform: translateY(-20px);*/
}

.ngr-popup-content {
  margin: 0 !important;
}

.ngr-popup-content p {
  margin: 6px 0 !important;
}

.ngr-popup-content div {
  line-height: 20px;
}

.ngr-popup-content .room-name {
  color: black;
}

.ngr-left .ngr-control {
  margin-left: 20px !important;
  margin-bottom: 10px !important;
}
</style>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.spin-icon-load {
  animation: newRotate 2s linear infinite;
}

@keyframes newRotate {
  0% {
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(180deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.map-container {
  position: absolute;
  border: 1px solid #ddd;
  width: calc(100% - 30px);
  height: calc(100% - 80px);
}

#map {
  height: 100%;
  background: #fff;
}

.animation-player-container {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 300px;
  padding-bottom: 4px;
}
</style>
